package com.lyc.project.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyc.common.model.entity.InterfaceInfo;
import com.lyc.common.model.entity.Order;
import com.lyc.common.model.entity.User;
import com.lyc.common.model.entity.UserInterfaceInfo;
import com.lyc.project.common.ErrorCode;
import com.lyc.project.constant.TimeConstant;
import com.lyc.project.exception.BusinessException;
import com.lyc.project.mapper.OrderMapper;
import com.lyc.project.model.dto.order.OrderAddRequest;
import com.lyc.project.model.dto.order.OrderDeleteRequest;
import com.lyc.project.model.dto.order.OrderPayRequest;
import com.lyc.project.model.dto.order.OrderQueryRequest;
import com.lyc.project.model.enums.OrderStatusEnum;
import com.lyc.project.model.vo.OrderVO;
import com.lyc.project.service.InterfaceInfoService;
import com.lyc.project.service.TOrderService;
import com.lyc.project.service.UserInterfaceInfoService;
import com.lyc.project.service.UserService;
import com.lyc.project.utils.OrderMqUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Linyichengzi
* @description 针对表【api_order(api订单表)】的数据库操作Service实现
* @createDate 2023-08-22 11:00:34
*/
@Slf4j
@Service
public class TOrderServiceImpl extends ServiceImpl<OrderMapper, Order>
    implements TOrderService {
    
    @Resource
    UserService userService;
    
    @Resource
    InterfaceInfoService interfaceInfoService;
    
    @Resource
    UserInterfaceInfoService userInterfaceInfoService;

    @Resource
    private OrderMqUtils orderMqUtils;

    /**
     * 添加订单
     * @param orderAddRequest
     * @param request
     * @return
     */
    @Transactional
    @Override
    public OrderVO addOrder(OrderAddRequest orderAddRequest, HttpServletRequest request) {
        
        //1、订单服务校验，用户是否存在，接口是否存在等校验
        if(orderAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long userId = orderAddRequest.getUserId();
        Long interfaceInfoId = orderAddRequest.getInterfaceInfoId();
        Integer count = orderAddRequest.getCount();
        BigDecimal totalAmount = orderAddRequest.getTotalAmount();
        Double charging = orderAddRequest.getCharging();
        
        //如果用户和接口不存在
        if(userId == null || interfaceInfoId == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        //如果购买数量小于0
        if (count<=0 || totalAmount.compareTo(new BigDecimal(0)) < 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //用户是否存在
        User user = userService.getLoginUser(request);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR,"用户不存在");
        }
        //接口是否存在
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceInfoId);
        if(interfaceInfo == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "接口不存在");
        }
        // 后端校验订单总价格
        double temp = charging * count;
        BigDecimal bd = new BigDecimal(temp);
        double finalPrice = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        if (finalPrice != totalAmount.doubleValue()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "价格错误");
        }
        //2、数据库保存订单数据
        Order order = new Order();
        String orderNum = generateOrderNum(userId);
        order.setTotalAmount(orderAddRequest.getTotalAmount().doubleValue());
        order.setOrderSn(orderNum);
        order.setUserId(userId);
        order.setInterfaceInfoId(interfaceInfoId);
        order.setCount(count);
        order.setStatus(0);
        order.setCharging(charging);
        
        BeanUtils.copyProperties(orderAddRequest, order);
        boolean save = this.save(order);
        if (!save) {
            log.info("订单创建失败");
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        //3.同时消息队列发送延时消息
        orderMqUtils.sendOrderSnInfo(order);
        
        //4、构造订单详情
        OrderVO orderVO = new OrderVO();
        orderVO.setInterfaceInfoId(interfaceInfoId);
        orderVO.setUserId(userId);
        orderVO.setOrderNumber(orderNum);
        orderVO.setTotal(Long.valueOf(count));
        orderVO.setCharging(charging);
        orderVO.setTotalAmount(totalAmount.doubleValue());
        orderVO.setStatus(order.getStatus());
        orderVO.setInterfaceDesc(interfaceInfo.getDescription());
        orderVO.setInterfaceName(interfaceInfo.getName());
        DateTime date = DateUtil.date();
        orderVO.setCreateTime(date);
        // 设置过期时间
        orderVO.setExpirationTime(DateUtil.offset(date, DateField.MILLISECOND, TimeConstant.Expiration_Time));
        return orderVO;
    }

    // 刪除订单，根据订单号查询然后删除
    @Override
    public boolean deleteOrder(OrderDeleteRequest orderDeleteRequest, HttpServletRequest request) {
        String orderNumber = orderDeleteRequest.getOrderNumber();
        if (orderNumber == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getOrderSn,orderNumber);
        Order order = this.getOne(lambdaQueryWrapper);
        Long id = order.getId();
        boolean delete = this.removeById(id);
        if(!delete) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return true;
    }

    // 支付订单，修改用户接口调用次数和修改订单状态
    @Transactional
    @Override
    public boolean payOrder(OrderPayRequest orderPayRequest, HttpServletRequest request) {
        String orderNumber = orderPayRequest.getOrderNumber();
        if (orderNumber == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getOrderSn,orderNumber);
        Order order = this.getOne(lambdaQueryWrapper);
        Long interfaceInfoId = order.getInterfaceInfoId();
        Long userId = order.getUserId();
        Integer count = order.getCount();
        LambdaQueryWrapper<UserInterfaceInfo> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UserInterfaceInfo::getInterfaceInfoId, interfaceInfoId).eq(UserInterfaceInfo::getUserId, userId);
        UserInterfaceInfo userInterfaceInfo = userInterfaceInfoService.getOne(lqw);
        // 如果用户第一次使用这个接口，就为用户创建userInterfaceInfo数据，否则就找到并leftNum增加
        if(userInterfaceInfo == null) {
            // 添加数据
            UserInterfaceInfo addUserInterfaceInfo = new UserInterfaceInfo();
            addUserInterfaceInfo.setUserId(userId);
            addUserInterfaceInfo.setInterfaceInfoId(interfaceInfoId);
            addUserInterfaceInfo.setTotalNum(0);
            addUserInterfaceInfo.setLeftNum(Math.toIntExact(count));
            addUserInterfaceInfo.setStatus(0);
            boolean save = userInterfaceInfoService.save(addUserInterfaceInfo);
            if(!save){
                throw new BusinessException(ErrorCode.OPERATION_ERROR);
            }
        }
        // 如果不是第一次使用这个接口，数据库已经有这个数据，直接在leftNum增加
        else {
            LambdaUpdateWrapper<UserInterfaceInfo> upLqw = new LambdaUpdateWrapper<>();
            upLqw.eq(UserInterfaceInfo::getUserId, userId);
            upLqw.eq(UserInterfaceInfo::getInterfaceInfoId, interfaceInfoId);
            upLqw.setSql("leftNum = leftNum + " + count);
            boolean update = userInterfaceInfoService.update(upLqw);
            if (!update) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR);
            }
        }
        // 最后如果次数添加成功，将订单的状态修改为已支付，从0变成1
        Long OrderId = order.getId();
        Order newOrder = new Order();
        newOrder.setId(OrderId);
        newOrder.setTotalAmount(order.getTotalAmount());
        newOrder.setStatus(OrderStatusEnum.PAY.getValue());
        boolean updateOrder = this.updateById(newOrder);
        if(!updateOrder){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
            // 如果修改失败，订单回滚,使得接口调用次数减回来，如果payOrder添加注解@Transactional还是否需要？
            // 因为添加了Transactional注解，不需要回滚操作
        }
        // 最后都成功后，直接返回true
        return true;
    }

    /**
     * 获取分页数据
     * @param orderQueryRequest
     * @param request
     * @return
     */
    @Override
    public Page<OrderVO> listPageOrder(OrderQueryRequest orderQueryRequest, HttpServletRequest request) {
        Integer type = Integer.parseInt(orderQueryRequest.getType());
        long pageSize = orderQueryRequest.getPageSize();
        long current = orderQueryRequest.getCurrent();
        if (!OrderStatusEnum.getValues().contains(type)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User userVO = userService.getLoginUser(request);
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userVO.getId()).eq("status", type);
        Page<Order> page = new Page(current, pageSize);
        Page<Order> orderPage  = this.page(page, queryWrapper);
        Page<OrderVO> orderVOPage = new Page<>(orderPage.getCurrent(), orderPage.getSize(), orderPage.getTotal());

        List<OrderVO> orderVOList = orderPage.getRecords().stream().map(order -> {
            Long interfaceInfoId = order.getInterfaceInfoId();
            InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceInfoId);
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            orderVO.setOrderNumber(order.getOrderSn());
            orderVO.setInterfaceName(interfaceInfo.getName());
            orderVO.setInterfaceDesc(interfaceInfo.getDescription());
            orderVO.setTotal(Long.valueOf(order.getCount()));
            orderVO.setTotalAmount(order.getTotalAmount());
            orderVO.setCreateTime(order.getCreatTime());
            orderVO.setExpirationTime(DateUtil.offset(order.getCreatTime(), DateField.MILLISECOND,TimeConstant.Expiration_Time));
            return orderVO;
        }).collect(Collectors.toList());
        orderVOPage.setRecords(orderVOList);
        return orderVOPage;
    }

    /**
     * 生成订单号
     * @param userId
     * @return
     */
    private String generateOrderNum(Long userId) {
        String timeId = IdWorker.getTimeId();
        String substring = timeId.substring(0, timeId.length() - 15);
        return substring + RandomUtil.randomNumbers(5) + userId;
    }
}




